//
// Created by Martin on 2023/4/25.
//

#include "muduo/net/TcpClient.h"
#include "muduo/net/EventLoop.h"
#include "muduo/base/Logging.h"

#include <stdio.h>
#include <unistd.h>

#include <string>

using namespace muduo;
using namespace muduo::net;

int numThreads = 0;

class FtpClient;
std::vector<std::unique_ptr<FtpClient>> clients;
int current = 0;

class FtpClient : noncopyable
{
public:
    FtpClient(EventLoop* loop, const InetAddress& listenAddr, const string& id)
    : loop_(loop), client_(loop, listenAddr, "FtpClient" + id)
    {
        client_.setConnectionCallback(std::bind(&FtpClient::onConnection, this, _1));
        client_.setMessageCallback(std::bind(&FtpClient::onMessage, this, _1, _2, _3));
    }

    void connect()
    {
        client_.connect();
    }

private:

    void onConnection(const TcpConnectionPtr& conn)
    {
        LOG_TRACE << conn->localAddress().toIpPort() << " -> "
        << conn->peerAddress().toIpPort() << " is "
        << (conn->connected() ? "UP" : "DOWN");

        if (conn->connected()) {
            ++current;
            // next client connect to server
            if (static_cast<size_t>(current) < clients.size()) {
                clients[static_cast<size_t>(current)]->connect();
            }
            LOG_INFO << "*** Ftp client connected " << current;
            conn->send("SYST\r\n");
        }
    }

    void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp timestamp)
    {
        string msg(buf->retrieveAllAsString());
        LOG_TRACE << conn->name() << "recv " << msg.size() << " bytes";
    }

    EventLoop* loop_;
    TcpClient client_;
};

constexpr int listenPort = 2008; // keep same with server

int main(int argc, char* argv[])
{
    LOG_INFO << "pid = " << getpid() << ", tid = " << CurrentThread::tid();
    if (argc > 1) {
        EventLoop loop;
        InetAddress serverAddr(argv[1], listenPort);

        int n = 1;
        if (argc > 2) {
            n = atoi(argv[2]);
        }

        clients.reserve(static_cast<size_t>(n));
        for (int i = 0; i < n; ++i) {
            char buf[32];
            snprintf(buf, sizeof(buf), "%d", i + 1);
            clients.emplace_back(new FtpClient(&loop, serverAddr, buf));
        }

        clients[static_cast<size_t>(current)]->connect();
        loop.loop();
    }
    else {
        printf("Usage: %s host ip\n", argv[0]);
    }
    return 0;
}
